﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Interactivity;
using Avalonia.Styling;

namespace ExcelMerge;

public partial class MergeView : UserControl
{
    public ObservableCollection<RowData> SelfRowData { get; } = new();
    public ObservableCollection<RowData> OtherRowData { get; } = new();
    public ObservableCollection<RowData> OutputRowData { get; } = new();

    private MergeModel _model;
    public MergeView(object args)
    {
        if (args is not MergeModel argument)
        {
            throw new Exception("参数类型不对:" + args.GetType().FullName);
        }

        _model = argument;
        InitializeComponent();
        
        InitTable(SelfGrid,_model.ColCount,"Mine");
        InitTable(OtherGrid,_model.ColCount,"Theirs");
        InitTable(MergedGrid,_model.ColCount,"Merged");
        
        LoadData(SelfGrid,SelfRowData,argument.SelfItems);
        LoadData(OtherGrid,OtherRowData,argument.OtherItems);
        
        RefreshUI();
    }

    private void InitTable(DataGrid grid,int colCount,string dataName)
    {
        Application.Current.TryGetResource("DataGridLineCellThem", out var lineThem);
        grid.Columns.Add(new DataGridTextColumn
        {
            Header = dataName,
            Binding = new Binding("Cells[0].Value"),
            Width = new DataGridLength(1, DataGridLengthUnitType.Auto),
            CellTheme = lineThem as ControlTheme,
        });
        
        for (int i = 1; i <= colCount; i++)
        {
            grid.Columns.Add(new IndexColumn(i)
            {
                CellTemplate = Resources["DataGridCellTemplate"] as IDataTemplate,
            });
        }
    }

    private void LoadData(DataGrid grid,ObservableCollection<RowData> data,List<CellDiffItem> cells)
    {
        data.Clear();
        int index = 1;
        var rowData = new RowData(index);
        foreach (var cell in cells)
        {
            rowData.AddCell(cell);
            if (cell.IsLineFeed())
            {
                data.Add(rowData);
                index++;
                rowData = new RowData(index);
            }
        }
        grid.ItemsSource = data;
    }

    private void RefreshUI()
    {
        LoadData(MergedGrid,OutputRowData,_model.GetMergedItems());
        
        UseMineBtn.IsEnabled = _model.HasConflict();
        UseTheirsBtn.IsEnabled = _model.HasConflict();
        UseMineAllBtn.IsEnabled = _model.HasConflict();
        UseTheirsAllBtn.IsEnabled = _model.HasConflict();
        UndoBtn.IsEnabled = _model.HasLastStep();
        RedoBtn.IsEnabled = _model.HasNextStep();
        SaveBtn.IsEnabled = !_model.HasConflict();

        if (!_model.HasConflict())
        {
            return;
        }

        if (OutputRowData.Count > 0)
        {
            var lastMergedRow = OutputRowData[^1];
            if (lastMergedRow.Cells.Count >= MergedGrid.Columns.Count)
            {
                MergedGrid.ScrollIntoView(lastMergedRow,MergedGrid.Columns[0]);
            }
            else
            {
                MergedGrid.ScrollIntoView(lastMergedRow,MergedGrid.Columns[lastMergedRow.Cells.Count - 1]);
            }
        }
    }

    private void UndoBtn_OnClick(object? sender, RoutedEventArgs e)
    {
        _model.LastStep();
        RefreshUI();
    }

    private void RedoBtn_OnClick(object? sender, RoutedEventArgs e)
    {
        _model.NextStep();
        RefreshUI();
    }

    private void UseTheirsAllBtn_OnClick(object? sender, RoutedEventArgs e)
    {
        _model.ManualMergeAll(false);
        RefreshUI();
    }

    private void UseMineAllBtn_OnClick(object? sender, RoutedEventArgs e)
    {
        _model.ManualMergeAll(true);
        RefreshUI();
    }

    private void UseTheirsBtn_OnClick(object? sender, RoutedEventArgs e)
    {
        _model.ManualMerge(false);
        RefreshUI();
    }

    private void UseMineBtn_OnClick(object? sender, RoutedEventArgs e)
    {
        _model.ManualMerge(true);
        RefreshUI();
    }

    private void SaveBtn_OnClick(object? sender, RoutedEventArgs e)
    {
        _model.Apply();
        Environment.Exit(1);
    }
}